package stockGP;

import java.util.ArrayList;
import java.util.Random;

import main.Stock;

public class TreeNode {

	ArrayList<TreeNode> children;
	TreeNode parent;
	static int days;
	String operation;
	int serialNum;
	public double evaluateSubtree(Stock stock, int start){
		
		if(operation.startsWith("x")){
			return stock.getPrices().get(start+Integer.parseInt(operation.substring(1)));
		}
		if(Character.isDigit(operation.charAt(0))){
			return Double.parseDouble(operation);
		}
		if(operation.intern()==">"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			if(res1>res2)
				return 1;
			else
				return 0;
		}
		if(operation.intern()=="<"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			if(res1<res2)
				return 1;
			else
				return 0;
		}
		if(operation.intern()=="="){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			if(res1==res2)
				return 1;
			else
				return 0;
		}
		if(operation.intern()=="and"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			if(res1==1 && res2==1)
				return 1;
			else
				return 0;
		}
		if(operation.intern()=="or"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			if(res1==1 || res2==1)
				return 1;
			else
				return 0;
		}
		if(operation.intern()=="+"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			return res1+res2;
		}
		if(operation.intern()=="-"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			return res1-res2;
		}
		if(operation.intern()=="*"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			return res1*res2;
		}
		if(operation.intern()=="/"){
			double res1=children.get(0).evaluateSubtree(stock, start);
			double res2=children.get(1).evaluateSubtree(stock, start);
			if(res2!=0)
				return res1/res2;
			else
				return res1;
		}
		if(operation.intern()=="mv"){
			return movAvg(stock);
		}
		
		return 0;
	}
	
	
	private double movAvg(Stock stock) {
		// TODO Auto-generated method stub
		return 100;
	}
	public TreeNode(ArrayList<TreeNode> children, String operation,int num) {
		super();
		this.children = children;
		this.operation = operation;
		this.serialNum=num;
	}
	
	public TreeNode(TreeNode root) {
		// TODO Auto-generated constructor stub
		this.operation=root.operation;
		this.serialNum=root.serialNum;
		if(root.children.size()==0)
			children=new ArrayList<TreeNode>();
		else{
			children=new ArrayList<TreeNode>();
			children.add(new TreeNode(root.children.get(0)));
			children.add(new TreeNode(root.children.get(1)));
		}
			
		
	}


	public void mutation(int MUTATION_RATE){
		Random r = new Random();
		int num;

		num = r.nextInt(MUTATION_RATE);
		// the case that this chromosome will have a mutation on him
		if(num == 0){
		
			if(children.size()==2){
				num=r.nextInt(9);
				String[] operations={">","<","=","and","or","*","/","+","-"};
				operation=operations[num];
			}
			else
			{
				num=r.nextInt(3);
				
				if(num==0){
					int index=r.nextInt(days);
					operation="x"+index;
				}
				if(num==1){
					int index=r.nextInt(1000);
					operation=String.valueOf(index);
				}
				if(num==2){
					operation="mv";
				}
				
			}
		}
		for(TreeNode node:children){
			node.mutation(MUTATION_RATE);
		}
	}
	public void print(int depth) {
		System.out.println("the operation: " + operation + " in depth: " + depth+" serial "+serialNum);
		for (TreeNode node : children) {
			node.print(depth+1);
		}
	}
	
	public int getLength(){
		int sum=0;
		for(TreeNode child:children){
			sum+=child.getLength();
		}
		return 1+sum;
	}
	
	public void crossover(){
		
		Random r = new Random();
		int num;

		num = r.nextInt(getLength());
		
		if(num == 0){
			
		}
	}
	
	public void chooseRand(int len){
		Random r=new Random();
		int num=r.nextInt(len);
	}
	public TreeNode search(int num) {
		if(num==serialNum)
			return this;
		else{
			if(children.size()==2){
				if(children.get(0).search(num)!=null)
					return children.get(0).search(num);
				else if(children.get(1).search(num)!=null)
					return children.get(1).search(num);
				else
					return null;
				
			}
			else{
				return null;
			}
		}
	}


	public void fix() {
		// TODO Auto-generated method stub
		if(children.size()==0)
			serialNum=-1;
		else{
			children.get(0).fix();
			children.get(1).fix();
			serialNum=Tree.count++;
		}
	}
}
